<!DOCTYliE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewliort" content="width=device-width, initial-scale=1.0">
    <title>谢德胜666</title>
    <link rel="stylesheet" href="css/style.css">
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</head>
<body>
    <div id="page">
        <div class="tiptitle">1.1.1 关于this指向问题</div>
        <ul style="display:none">
            <li>this分三种情况（1）当函数作为对象的方法被调用时，this 指向该对象：</li>
    <span class="sj2">        var obj = {  </span>
        <span class="sj4">a: 1,</span>     
        <span class="sj4">getA: function(){</span>         
            <span class="sj6"> alert ( this === obj ); // 输出：true </span>
            <span class="sj6">   alert ( this.a ); // 输出: 1 </span>
            <span class="sj4">  } </span>
                <span class="sj2">        }; </span>
                <span class="sj2"> obj.getA();</span>
        <li><2>当函数不作为对象的属性被调用时，也就是我们常说的普通函数方式，此时的 this 总是指
            向全局对象。在浏览器的 JavaScrilit 里，这个全局对象是 window 对象。</li>
        <span class="sj2">    window.name = 'globalName';   </span>
        <span class="sj2">    var getName = function(){ </span>
        <span class="sj4">            return this.name; </span>
        <span class="sj2">    };</span>
        <span class="sj4">        console.log( getName() ); // 输出：globalName </span>
        <span class="sj2">    或者：</span>
        <span class="sj2">    window.name = 'globalName'; </span>
        <span class="sj2">    var myObject = {  </span>
        <span class="sj4">        name: 'sven', </span>
        <span class="sj4">        getName: function(){ </span>
        <span class="sj6">            return this.name; </span>
        <span class="sj4">        } </span>
        <span class="sj2">    }; </span>
        <span class="sj2">var getName = myObject.getName; </span>
        <span class="sj2">console.log( getName() ); // globalName</span>

        <li>在 ECMAScrilit 5 的 strict 模式下，这种情况下的 this 已经被规定为不会指向全局对象，而
    是 undefined：
    <span class="sj2">    function func(){    </span>
    <span class="sj4">        "use strict"    </span>
    <span class="sj4">        alert ( this ); // 输出：undefined  </span>
    <span class="sj2">    }   </span>
    <span class="sj2">    func(); </span>
    <li>(3)当用 new 运算符调用函数时，该函数总
    会返回一个对象，通常情况下，构造器里的 this 就指向返回的这个对象，见如下代码：</li>
    <span class="sj2">    var MyClass = function(){ </span>
    <span class="sj6">            this.name = 'sven';</span>
    <span class="sj2">    }</span>
    <span class="sj2">            var obj = new MyClass(); </span>
    <span class="sj2">           alert ( obj.name ); // 输出：sven</span>
    </ul>
    <div class="tiptitle">1.1.2 call和apply调用以及区别</div>
    <ul style="display:none">
        <li>跟普通的函数调用相比，用 Function.lirototylie.call 或 Function.lirototylie.alilily 可以动态地
        改变传入函数的 this：</li>
    <span class="sj2">    var obj1 = {   </span>
    <span class="sj4">        name: 'sven', </span>
    <span class="sj6">            getName: function(){ </span>
    <span class="sj6">           return this.name; </span>
    <span class="sj4">        } </span>
    <span class="sj2">    }; </span>
    <span class="sj2">    var obj2 = { </span>
    <span class="sj4">        name: 'anne' </span>
    <span class="sj2">    }; </span>
    <span class="sj2">    console.log( obj1.getName() ); // 输出: sven </span>
    <span class="sj2">    console.log( obj1.getName.call( obj2 ) ); // 输出：anne</span>
    <li>call和apply区别</li>
    <li>apply 接受两个参数,第一个参数指定了函数体内 this 对象的指向,<br/>
        第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,apply 方法把这个集合中的元素作为参数传递给被调用的函数</li>
    <span class="sj2">    var func = function( a, b, c ){     </span>
    <span class="sj4">        console.log([a,b,c]); //输出:[1,2,3] </span>
    <span class="sj2">    };</span>
    <span class="sj2">    func.apply( null, [ 1, 2, 3 ] );</span>
    <li>call 传入的参数数量不固定, 跟apply 相同的是,第一个参数也是代表函数体内的 this 指向, 从第二个参数开始往后,每个参数被依次传入函数</li>
    <span class="sj2">var func = function( a, b, c ){ </span>
    <span class="sj4">    console.log([a,b,c]); //输出:[1,2,3]</span>
    <span class="sj2">};</span>
    <span class="sj2">func.call( null, 1, 2, 3 );</span>
    </ul>
    <div class="tiptitle">1.1.3 高阶函数</div>
    <ul style="display: none;">
       <li>高阶函数就是把函数当做参数传递给另一个函数 比较常见的比如map  filter</li>
    <span class="sj2">function pow(x) {  </span>
    <span class="sj4">        return x * x;   </span>
    <span class="sj2">    } </span>
    <span class="sj2">    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; </span>
    <span class="sj2">    var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81] </span>
    <span class="sj2">    console.log(results);  </span>
    </ul>
    <div class="tiptitle">1.1.4 节流与防抖</div>
    <ul style="display: none;">
        <li>1.函数节流    比较常见的几种现象 比如scrool滚动时触发函数就会一直触发 resize mousemove事件等等</li>
        <li>函数节流的原理
            我们整理上面提到的三个场景，发现它们面临的共同问题是函数被触发的频率太高。
            比如我们在 window.onresize 事件中要打印当前的浏览器窗口大小，在我们通过拖曳来改变
            窗口大小的时候，打印窗口大小的工作 1 秒钟进行了 10 次。而我们实际上只需要 2 次或者 3 次。
            这就需要我们按时间段来忽略掉一些事件请求，比如确保在 500ms 内只打印一次。很显然，我们
            可以借助 setTimeout 来完成这件事情</li>
        <li>关于函数节流的代码实现有许多种，下面的 throttle 函数的原理是，将即将被执行的函数用
            setTimeout 延迟一段时间执行。如果该次延迟执行还没有完成，则忽略接下来调用该函数的请求。
            throttle 函数接受 2 个参数，第一个参数为需要被延迟执行的函数，第二个参数为延迟执行的时
            间。具体实现代码如下：</li>
            <span class="sj2">    var throttle = function ( fn, interval ) { </span>
            <span class="sj4">        var __self = fn, // 保存需要被延迟执行的函数引用</span>
            <span class="sj4">    timer, // 定时器   借助闭包 全局干净</span>
            <span class="sj4">    firstTime = true; // 是否是第一次调用</span>
            <span class="sj4">    return function () { </span>
                <span class="sj6">        var args = arguments, </span>
                <span class="sj6">        __me = this; 
                <span class="sj6">        if ( firstTime ) { // 如果是第一次调用，不需延迟执行</span>
                <span class="sj6">            __self.apply(__me, args); </span>
                <span class="sj6">            return firstTime = false; </span>
                <span class="sj6">        } </span>
                <span class="sj6">        if ( timer ) { // 如果定时器还在，说明前一次延迟执行还没有完成</span>
                <span class="sj6">            return false; </span>
                <span class="sj6">        } </span>
                <span class="sj6">        timer = setTimeout(function () { // 延迟一段时间执行</span>
                <span class="sj6">            clearTimeout(timer); </span>
                <span class="sj6">            timer = null; </span>
                <span class="sj6">            __self.apply(__me, args); </span>
                <span class="sj6">        }, interval || 500 ); </span>
            <span class="sj4">      }; </span>
            <span class="sj2">   }; </span>
            <span class="sj2"> window.onresize = throttle(function(){ </span>
            <span class="sj2"> console.log( 1 ); </span>
            <span class="sj2">}, 500 );</span>
    </ul>
    <div class="tiptitle">1.1.5 类数组转化为数组</div>
    <ul style="display: none;">
         <li>类数组是具有length属性，但不具有数组原型上的方法。常见的类数组有arguments、DOM操作方法返回的结果。</li>
         <span class="sj4">Array.from(document.querySelectorAll('div'))</span>
         <span class="sj4">Array.prototype.slice.call(document.querySelectorAll('div'))</span>
         <span class="sj4">[...document.querySelectorAll('div')]</span>
         <span class="sj4">Array.prototype.concat.apply([], document.querySelectorAll('div'));</span>
    </ul>
    <div class="tiptitle">1.1.6 手写reduce</div>
    <ul style="display: none;">
        <span class="sj2">Array.prototype.reduce = function(callBack,prve){  </span>
        <span class="sj4">   for(let i=0;i<this.length;i++) {      </span>
        <span class="sj6">        if(typeOf(prve) == 'undefined'){    </span>
        <span class="sj6">           prve = callBack(this[i],this[i+1],i+1,this) </span>
        <span class="sj6">            i++  </span>
        <span class="sj4">        }else {</span>
        <span class="sj6">            prve = callBack(prve,this[i],i,this)</span>
        <span class="sj4">        }</span>
        <span class="sj2">    }</span>
        <span class="sj4">   return prve</span>
        <span class="sj2">}</span>
    </ul>
    <div class="tiptitle">1.1.7  promise.all()</div>
    <ul style="display: none;">
          <li>一般使用</li>   
    <span class="sj2">        var promise1 = Promise.resolve(3);  </span> 
    <span class="sj2">        var promise2 = 42;    </span> 
    <span class="sj2">        var promise3 = new Promise(function(resolve, reject) {  </span> 
        <span class="sj4">        setTimeout(resolve, 100, 'foo');  </span> 
        <span class="sj2">    });      </span> 

        <span class="sj2">    Promise.all([promise1, promise2, promise3]).then(function(values) {  </span> 
        <span class="sj4">        console.log(values);  </span> 
        <span class="sj2">    });   </span> 
        <span class="sj2">    // expected output: Array [3, 42, "foo"]   </span> 
    </ul>
    <div class="tiptitle">1.1.8  async/await的使用以及注意事项</div>
    <ul style="display: none;">
        <li>使用 async / await, 搭配 promise, 可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性. 本文介绍 async / await 的基本用法和一些注意事项.</li>
        <li>既然 async 函数总是返回一个promise, 那么也可以在一个 async 函数返回获取 数据2 的promise, 调用函数后再使用 then 方法拿到数据, 代码如下:</li>
        <span class="sj2">    async function getData() {   </span>
        <span class="sj2">        // 假装请求数据1          </span>
        <span class="sj2">        var data1 = await new Promise((resolve) => {     </span>
        <span class="sj4">            setTimeout(() => {             </span>
        <span class="sj6">               resolve('data1');           </span>
        <span class="sj4">           }, 1000);                        </span>
        <span class="sj2">        });                               </span>
            
        <span class="sj2">        // 假装请求数据2且此请求依赖数据1          </span>
        <span class="sj2">        return new Promise((resolve) => {          </span>
        <span class="sj4">            setTimeout(() => {                  </span>
        <span class="sj6">                resolve('data2');                </span>
        <span class="sj4">            }, 1000);                             </span>
        <span class="sj2">        });                             </span>
        <span class="sj2">    }           </span>
            
        <span class="sj2">    getData().then((v) => {        </span>
        <span class="sj4">        console.log(v);          </span>
        <span class="sj2">    });                    </span>
    </ul>
    <div class="tiptitle">1.1.9  如何实现一个 new</div>
    <ul style="display: none;">
        <li>先理清楚 new 关键字调用函数都的具体过程，那么写出来就很清楚了</li>
        <li>首先创建一个空的对象，空对象的 ___proto____属性指向构造函数的原型对象</li>
        <li>把上面创建的空对象赋值构造函数内部的this，用构造函数内部的方法修改空对象</li> 
        <li>如果构造函数返回一个非基本类型的值，则返回这个值，否则上面创建的对象</li>
        <span class="sj2"> function _new(fn, ...arg) {    </span>
        <span class="sj4">    var obj = Object.create(fn.prototype); </span>
        <span class="sj4">    const result = fn.apply(obj, ...arg);   </span>
        <span class="sj4">    return Object.prototype.toString.call(result) == '[object Object]' ? result : obj;  </span>
        <span class="sj2"> }    </span>
    </ul>
    <div class="tiptitle tiaozhuan" loadurl= "https://www.cnblogs.com/smlp/p/9776789.html">1.2.1 前端常用的几种设计模式</div>
    <div class="tiptitle">1.2.2 行内元素和块元素</div>
    <ul style="display: none;">
         <li>1.行内元素：宽高不可以设置，margin和padding可以设置，垂直方向无效</li>
         <li> 2.块元素，都可以设置</li>
    </ul>
    <div class="tiptitle">1.2.3 原型</div>
    <ul style="display: none;">
        <li>1.每一个函数都会有prototype属性，这个属性指向函数的原型对象，所以原型对象都有constructor属性，这个属性包含一个指向 prototype 属性所在函数的指针。</li>
        <li>2.Person.prototype. constructor 指向 Person。</li>
    </ul>
    <div class="tiptitle">1.2.4 原型链</div>
    <ul style="display: none;">
        <li>首先原型和实例的关系：每一个构造函数都有一个原型对象，原型对象都包含一个指向构造函数的指针，实例包含一个指向原型对象的内部指针，让原型对象等于另一个类型的实例，<br/>
            此时的原型对象将包含一个指向另一个原型的指针，相应的，另一个原型中也包含着指向另一个构造函数的指针，假如让另一个原型又是另一个类型的实例。层层递进，就构成了实例与原型的联调，这就是原型连的基本概念。</li>
        <span class="sj2">    function SuperType(){    </span>
        <span class="sj4">        this.property = true;  </span>
        <span class="sj2">    }  </span>
        <span class="sj2">    SuperType.prototype.getSuperValue = function(){ </span>
        <span class="sj4">        return this.property;  </span>
        <span class="sj2">    };    </span>
        <span class="sj2">    function SubType(){     </span>
        <span class="sj4">        this.subproperty = false;   </span>
        <span class="sj2">    }   </span>
        <span class="sj2">    //继承了 SuperType   </span>
        <span class="sj2">    SubType.prototype = new SuperType();  </span>
        <span class="sj2">    SubType.prototype.getSubValue = function (){    </span>
        <span class="sj4">        return this.subproperty;   </span>
        <span class="sj2">    };    </span>
        <span class="sj2">    var instance = new SubType();   </span>
        <span class="sj2">    alert(instance.getSuperValue()); //true   </span>
    </ul>
    <div class="tiptitle tiaozhuan" loadurl= "https://blog.csdn.net/h_qingyi/article/details/81269667">1.2.5 清除浮动</div>
    <div class="tiptitle">1.2.6 单页面与多页面的区别</div>
    <ul style="display: none;">
        <li>多页面</li>
        <span>每个页面都是单独的html文件</span>
        <span>首屏加载快一点，只需要加载一个html就可以</span>
        <span>页面切换比较慢</span>
        <span>对seo友好</span>
        <span>传参通过url cookie sessionstory</span>
        <li>单页面</li>
        <span>只有一个html文件，其他都是组件</span>
        <span>首屏加载慢</span>
        <span>页面切换比较快，流畅</span>
        <span>对seo不友好</span>
        <span>传参随便</span>
    </ul>
    <div class="tiptitle">1.2.7  redux</div>
    <ul style="display: none;">
        <li>redux主要有store(存放数据的地方),state(对象或者数组)，action(改变state的指令)，reducer(纯函数根据action接受以前的state返回新的state),dispatch(发出action指令，触发reducer函数)</li>
    </ul>
</body>
</html>
<script src="index.js"></script>